package com.hxjy.dao.impl;

import java.io.Serializable;
import java.lang.reflect.InvocationTargetException;
import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.ResultSetMetaData;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.apache.commons.beanutils.BasicDynaClass;
import org.apache.commons.beanutils.DynaBean;
import org.apache.commons.beanutils.DynaClass;
import org.apache.commons.beanutils.DynaProperty;
import org.apache.commons.beanutils.PropertyUtils;
import org.hibernate.HibernateException;
import org.hibernate.Query;
import org.hibernate.Session;
import org.springframework.jdbc.core.BeanPropertyRowMapper;
import org.springframework.jdbc.datasource.DataSourceUtils;
import org.springframework.orm.hibernate3.HibernateCallback;
import org.springframework.stereotype.Repository;

import com.hxjy.base.DataTemplate;
import com.hxjy.constant.Constant;
import com.hxjy.dao.CommonDao;

/**
 * 通用数据库操作模版接口实现类
 * 
 * @author 李彬
 */
@Repository(value="commonDao")
@SuppressWarnings("unchecked")
public class CommonDaoImpl extends DataTemplate implements CommonDao {

	public int count(final String sql) {
		return this.getJdbcTemplate().queryForInt(sql);
	}
	
	public int count(final String sql,List<Object> params) {
		Object[] objs = new Object[params.size()];
		for (int i = 0; i < objs.length; i++) {
			objs[i] = params.get(i);
		}
		return this.getJdbcTemplate().queryForInt(sql,objs);
	}

	public void delete(final Object obj) {
		this.getHibernateTemplate().delete(obj);
	}

	public void delete(final List<Object> entities) {
		this.getHibernateTemplate().deleteAll(entities);
	}

	@SuppressWarnings("unchecked")
	public List<Object> find(final String hql, final List<Object> params) {
		List<Object> ret = null;
        try {
            if (hql == null || hql.equals("")) {
                return ret;
            }

            Object[] values = null;

            if (params != null && !params.isEmpty()) {
                values = new Object[params.size()];
                for (int i = 0; i < params.size(); i++) {
                    values[i] = params.get(i);
                }
            }
            ret = this.getHibernateTemplate().find(hql, values);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return ret;
	}

	public <T> T get(final Class<T> clazz, final Serializable id) {
		return (T) this.getHibernateTemplate().get(clazz, id);
	}

	public String getTimeFromDB() {
		
		return null;
	}

	@SuppressWarnings("unchecked")
	public List<Object> list(final String hql) {
		return this.getHibernateTemplate().find(hql);
	}

	@SuppressWarnings("unchecked")
	public List<Object> listForCustom(final String sql) {
		Connection con = null;
		Statement stm = null;
		ResultSet rs = null;
		ResultSetMetaData rsmd = null;
		List list = new ArrayList();

		int columns = 0;

		try {
			//con = jdbcTemplate.getDataSource().getConnection();
			con = DataSourceUtils.getConnection(super.getJdbcTemplate().getDataSource());
			/*
			 * Session session = HibernateSessionFactory.getSession();
			 * 
			 * con = session.connection();
			 */

			if (con == null)
				return null;
			stm = con.createStatement();
			if (stm == null)
				return null;
			rs = stm.executeQuery(sql);
			if (rs == null)
				return null;

			rsmd = rs.getMetaData();
			columns = rsmd.getColumnCount();
		} catch (SQLException e1) {
			e1.printStackTrace();
		}
		DynaProperty[] px = new DynaProperty[columns];
		String prop[] = new String[columns];

		for (int i = 0; i < columns; i++) {
			try {
				// 注意此处
				prop[i] = rsmd.getColumnLabel(i + 1);
			} catch (SQLException e1) {
				e1.printStackTrace();
			}
			try {
				px[i] = new DynaProperty(prop[i], Class
						.forName("java.lang.String"));

			} catch (ClassNotFoundException e) {
				e.printStackTrace();
				return null;
			}
		}

		DynaClass dynaClass = null;

		DynaBean dynaBean;

		try {
			while (rs.next()) {

				dynaClass = new BasicDynaClass("dynaBean", null, px);

				try {
					dynaBean = dynaClass.newInstance();
				} catch (IllegalAccessException e) {
					e.printStackTrace();
					return null;
				} catch (InstantiationException e) {
					e.printStackTrace();
					return null;
				}

				for (int i = 1; i <= columns; i++) {
					Object temp = rs.getObject(i);

					if (temp == null)
						temp = "";
					else
						temp = rs.getObject(i).toString();
					try {
						PropertyUtils.setProperty(dynaBean, prop[i - 1], temp);
					} catch (IllegalAccessException e) {
						e.printStackTrace();
						return null;
					} catch (InvocationTargetException e) {
						e.printStackTrace();
						return null;
					} catch (NoSuchMethodException e) {
						e.printStackTrace();
						return null;
					}
				}
				list.add(dynaBean);
			}
		} catch (SQLException e) {
			e.printStackTrace();
		} finally {
			try {
				if (rs != null)
					rs.close();
				if (stm != null)
					stm.close();
				if (con != null)
					con.close();
			} catch (SQLException e) {
				e.printStackTrace();
			}
		}
		return list;
	}

	@SuppressWarnings("unchecked")
	public Map<Object, Object> listForCustomToMap(final List<Object> list) {
		Map map = new HashMap();
		if(list.size()==0||list==null||list.isEmpty()){
			map = null;
			return map;
		}else{
			for (int i = 0; i < list.size(); i++) {
				try {
					map.put(i, PropertyUtils.describe(list.get(i)));
				} catch (IllegalAccessException e) {
					e.printStackTrace();
				} catch (InvocationTargetException e) {
					e.printStackTrace();
				} catch (NoSuchMethodException e) {
					e.printStackTrace();
				} 
			}
			return map;
		}
	}

	public void save(Object obj) {
		super.getHibernateTemplate().save(obj);
	}

	public void saveAll(final List<Object> entities) {
		super.getHibernateTemplate().saveOrUpdateAll(entities);
	}

	public void update(final Object obj) {
		super.getHibernateTemplate().update(obj);
	}

	public void updateAll(final List<Object> entities) {
		super.getHibernateTemplate().saveOrUpdateAll(entities);
	}

	public void updateByHql(final String hql, final List<Object> params) {
		this.getHibernateTemplate().execute(new HibernateCallback() {
			public Object doInHibernate(Session session) throws HibernateException,SQLException {
				Query query = session.createQuery(hql);
                 if (params != null && !params.isEmpty()) {
                     for (int i = 0; i < params.size(); i++) {
                         query.setParameter(i, params.get(i));
                     }
                 }
                 return query.executeUpdate();
			}
		});
	}

	public void updateOrDeleteByHql(final String hql, final List<Object> params) {
		this.getHibernateTemplate().execute(new HibernateCallback() {
			public Object doInHibernate(Session session)
					throws HibernateException {
				Query query = session.createQuery(hql);
				if (params != null && !params.isEmpty()) {
					for (int i = 0; i < params.size(); i++) {
						query.setParameter(i, params.get(i));
					}
				}
				return query.executeUpdate();
			}
		});
	}

	@Override
	public int count(String sql, Object[] objs) {
		return this.getJdbcTemplate().queryForInt(sql,objs);
	}
	@Override
	public List customQuery(String sql,List<Object> params,Class clazz) {
		Object[] objs = new Object[params.size()];
		for (int i = 0; i < params.size(); i++) {
			objs[i] = params.get(i);
		}
		List list = this.getJdbcTemplate().query(sql,objs, new BeanPropertyRowMapper(clazz));
		return list;
	}
	@Override
	public Object[] customQuery(String sql,String countSql,List<Object> params,Class clazz) {
		Object[] objs1 = new Object[params.size()];
		for (int i = 0; i < params.size(); i++) {
			objs1[i] = params.get(i);
		}
		List list = this.getJdbcTemplate().query(sql,objs1, new BeanPropertyRowMapper(clazz));
		Object[] objs2 = new Object[params.size()-2];
		for (int i = 0; i <  params.size()-2; i++) {
			objs2[i] = params.get(i);
		}
		int count = this.count(countSql,objs2);
		return new Object[]{list,count};
	}
	public Object[] query(String sql,String countSql,int offset,Class clazz) {
		List list = this.getJdbcTemplate().query(sql,new Object[]{offset,offset + Constant.MAX_PAGE_SIZE}, new BeanPropertyRowMapper(clazz));
		int count = this.count(countSql);
		return new Object[]{list,count};
	}
	@Override
	public List query(String sql,Object[] objs,Class clazz) {
		List list = this.getJdbcTemplate().query(sql,objs, new BeanPropertyRowMapper(clazz));
		return list;
	}
	@Override
	public void saveOrUpdate(Object object) {
		this.getHibernateTemplate().saveOrUpdate(object);
		
	}
}
